/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package client.network;

import client.*;
import client.controller.events.VisitorCreatedEvent;
import client.controller.events.VisitorDeletedEvent;
import client.controller.events.VisitorGuideEvent;
import client.controller.events.VisitorUpdatedEvent;
import common.model.Visitor;
import common.model.message.CreateMessage;
import common.model.message.DetailsForMessage;
import common.model.message.SetGuideMessage;
import common.model.message.UpdateMessage;
import common.model.message.UserDepartedMessage;
import java.io.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author nicolas
 */
public class NetworkWatcher extends Thread {

    final Logger logger = LoggerFactory.getLogger(NetworkWatcher.class);
    private NetworkClient client;   // ref to top-level client
    private BufferedReader in;   // stream coming from the server
    private String userName;

    public NetworkWatcher(NetworkClient c, BufferedReader i, String userName) {
        client = c;
        in = i;
        this.userName = userName;
    }

    @Override
    public void run() /* Read a server message, display it, repeat.
    A message can be:
    "WHO$$ n1 & p1 & .... nN & pN & "
    or     "(cliAddr,port): msg"

    "WHO$$" messages are reformatted in showWho(), but
    other messages are displayed immediately by calling
    showMsg() in the client.
     */ {
        String line;
        try {
            while ((line = in.readLine()) != null) {
                logger.debug("received from server : {}", line);
                if ((line.length() >= 6) && // "WHO$$ "
                        (line.substring(0, 5).equals("WHO$$"))) {
                    //showWho(line.substring(5).trim());
                } // remove WHO$$ keyword and surrounding space
                else if (line.contains("CREATE")) {
                    CreateMessage createMessage = new CreateMessage(line);
                    //If sender is not me
                    if (!createMessage.getVisitor().getUserName().equals(this.userName)) {
                        NetworkEventsDispatcher.getApplicationEventsDispatcher().fireVisitorCreatedEvent(
                                new VisitorCreatedEvent(this, createMessage.getVisitor()));
                        //When a new visitor arrives, we tell him we are here
                        this.client.sendMessage(new DetailsForMessage(client.getRefToLocalVisitor(),
                                createMessage.getVisitor().getUserName()));
                    }
                } else if (line.contains("DETAILSFOR")) {
                    //A user tell us something about him
                    //Unmarshalling the message..
                    DetailsForMessage detailsForMessage = new DetailsForMessage(line);
                    NetworkEventsDispatcher.getApplicationEventsDispatcher().fireVisitorCreatedEvent(
                            new VisitorCreatedEvent(this, new Visitor(
                            detailsForMessage.getVisitor())));
                } else if (line.contains("UPDATE")) {
                    UpdateMessage updateMessage = new UpdateMessage(line);
                    //If i did not send that message, i wanna update this visitor
                    if (!updateMessage.getVisitor().getUserName().equals(client.getRefToLocalVisitor().getUserName())) {
                        NetworkEventsDispatcher.getApplicationEventsDispatcher().fireVisitorUpdatedEvent(
                                new VisitorUpdatedEvent(this, updateMessage.getVisitor())); //end of fire
                    } //end of elseif update
                } else if (line.contains("DEPARTED")) {
                    //---We received a user departed message
                    UserDepartedMessage userDepartedMessage  = new UserDepartedMessage(line);
                    NetworkEventsDispatcher.getApplicationEventsDispatcher().fireVisitorDeletedEvent(
                            new VisitorDeletedEvent(this, userDepartedMessage.getVisitor()));

                } else if (line.contains("SETGUIDE")){
                    SetGuideMessage setGuideMessage = new SetGuideMessage(line);
                    NetworkEventsDispatcher.getApplicationEventsDispatcher().fireVisitorGuideEvent(
                            new VisitorGuideEvent(this,setGuideMessage.getUserName(), setGuideMessage.isGuide()));
                }else // show immediately
                {
                    logger.info("Unknown message arrived : {}", line);
                }
            }
        } catch (Exception e) // socket closure will cause termination of while
        { 
            logger.error("Link to Server lost! Connection closed : {}", e);
            System.exit(0);
        }
    } // end of run()

}
